#include "cc1111rf.h"
#include "global.h"
#include "string.h"

#include "immefont.h"

#include "blackhat-game2.h"
#include "blackhat-game2-immeio.h"
/* ******************************************************************
*                                                                   *
* This game operates as a client/server application. The IMME is    *
* the client and the donsdongle is the server. The IMME initiates   *
* communcations, manages data request, monitors exchange state,     *
* and desplays results back to the user via the LCD. The server     *
* simply processes requests by monitoring for a proper exchange,    *
* testing a security code for authroization, and returning an       *
* information request.                                              *
*                                                                   *
* Packet exchanging goes like this.                                 *
* IMME Sends Init Packet to initiate conversation    : initbyte --> *
* Don's Dongle Receives and sends OK or NOK          : <-- ok       *
* IMME Sends Security Code Packet with code          : secbyte -->  *
* Don's Donge checks security code and sends OK/NOK  : <-- ok       *
* IMME Sends Message Request for hello message (0)   : sendbyte --> *
* Don's Donge checks security code and sends OK/NOK  : <-- ok       *
* IMME Sends Done message                            : donebyte --> *
* Don's Donge checks security code and sends OK/NOK  : <-- ok       *
*                                                                   *
* Intent is to show several things to student.                      *
* - Radio interception                                              *
* - Packet based protocol                                           *
* - Fuzzable parameters in protocol exchange                        *
* - Extractable data from firmware (i.e. security code, hidden      *
*       messages)                                                   *
* - Security data left in source code                               *
*                                                                   *
* Future functionality:                                             *
* - User selects security code                                      *
* - User selects message request                                    *
*                                                                   *
****************************************************************** */

/*******************************************************************
* welcome to the cc1111usb application.
* this lib was designed to be the basis for your usb-app on the cc1111 radio.  hack fun!
*
* 
* best way to start is to look over the library and get a little familiar with it.
* next, put code as follows:
* * any initialization code that should happen at power up goes in appMainInit()
* * the main application loop code should go in appMainLoop()
* * usb interface code should go into appHandleEP5.  this includes a switch statement for any 
*      verbs you want to create between the client on this firmware.
*
* if you should need to change anything about the USB descriptors, do your homework!  particularly
* keep in mind, if you change the IN or OUT max packetsize, you *must* change it in the 
* EPx_MAX_PACKET_SIZE define, the desciptor definition (be sure to get the right one!) and should 
* correspond to the setting of MAXI and MAXO.
* 
****************************************************************** */

#define APP_NIC 0x42
#define NIC_RECV 0x1
#define NIC_XMIT 0x2
#define SNIFF_RECV 0x1

/*************************************************************************************************
 * Application Code - these first few functions are what should get overwritten for your app     *
 ************************************************************************************************/

xdata u32 recvCnt;
xdata u32 counter;
#define COUNTER_RESET 4096

// Packet Struct
xdata TransData td;
u8 pseq;                // Packet Sequence 0 = init, 1 = security, 2 = data, after that we are done = 0xFF

//Tried to put these in the header file but apparently the compiler doesn't like that
void reset_trans_data(TransData *in_td);
void rtn_data(TransData *in_td, u8 *tmpdata);
void build_packet(TransData *in_td, u8 pbyte, u8 *sdata);
void pad_data(TransData *in_td);

/* appMainInit() is called *before Interrupts are enabled* for various initialization things. */
void appMainInit(void)
{
    recvCnt = 0;
    counter = COUNTER_RESET;
    reset_trans_data(&td);
    pseq = 0;

    RxMode();
    //startRX();
}

/* appMain is the application.  it is called every loop through main, as does the USB handler code.
 * do not block if you want USB to work.                                                           */


void appMainLoop(void)
{

    xdata u8 rxmit_processbuffer;
    xdata u8* txmit_processbuffer = (xdata u8*) td;
    //u8 print_byte;            // Message to print byte designator
    //u8 tdata[MESSMAX];

    if (--counter == 0) {
        counter = COUNTER_RESET;
        
        // Here starts the packet management code
        // We transmit init, seccode, and data. Then we are done.
        // Send next packet in the sequence
        if (pseq == INITBYTE){
            // 0 == Send Init Packet
            build_packet(&td,pseq,0);
        }else if (pseq == SECBYTE){
            // 1 == Send Security Code Packet
            build_packet(&td,pseq,SECCODE);  
        }else if (pseq == SENDBYTE){
            // 2 == Send Send Packet with a byte for the requested message
            build_packet(&td,pseq,ATMESS);
        }else{
            // 256 = Exchange finished, reset comms
            build_packet(&td,DONEBYTE,0);
            pseq = -1;      // Reset to -1 because an increment follows with will make this 0
        }

        // Add padding bytes to find in transmission stream
#ifdef PAD
        pad_data(&td);
#endif

        //BH_immeLCDDebugPacket((u8*) td,td.plen + 1);         //NOTE: For printing we need to add one to account for the length byte
        BH_immeLCDDebugPacket(txmit_processbuffer,td.plen + 1);         //NOTE: For printing we need to add one to account for the length byte
        //Setting SSN is required for display. Low to pause and High to restart
        SSN = LOW;
        drawhex(1,9, pseq);                             //NOTE: This DOES NOT display, it should, but does not
        SSN = HIGH;
        pseq++;

        // Send packet. The length is zero because we are in variable mode. First byte of data is length
        // Notify us if this returns an error (0)
        if (!transmit(txmit_processbuffer, 0)){
            SSN = LOW;
            eraserow(4);
            drawstr(4,0,"TRANSMIT ERROR");
            SSN = HIGH;
        }
    }
/*
    // Receive left on, but not currently usable
    if (rfif)
    {
        lastCode[0] = 0xd;
        //IEN2 &= ~IEN2_RFIE;
        
        if(rfif & RFIF_IRQ_DONE)
        {
            rxmit_processbuffer = !rfRxCurrentBuffer;
            if(rfRxProcessed[rxmit_processbuffer] == RX_UNPROCESSED)
            {   // we've received a packet.  deliver it.
                LED_RED = !LED_RED;
                ++recvCnt;
                //immeLCDShowPacket();
                BH_immeLCDRecvPacket();

                recvCnt++;
                SSN = LOW;
                // Used to show that we are processing and not dead in the water
                drawhex(1,17, recvCnt);
                SSN = HIGH;

                // We should be checking for incoming data here.
                // We should be receiving one of three messages
                // OK - all is okay. Action: continue
                // NOK - all is not okay. Action: restart NOTE: Potential for Denial of Service here
                // MESS - the data that is being returned associated with our request. Action: continue

                // Set receive buffer to processed so it can be used again
                rfRxProcessed[rxmit_processbuffer] = RX_PROCESSED;
            }
        }

        rfif = 0;
        //IEN2 |= IEN2_RFIE;
    }
*/
}

/*************************************************************************************************
 * main startup code                                                                             *
 *************************************************************************************************/
void initBoard(void)
{
    clock_init();
    io_init();
}


void main (void)
{
start:
    initBoard();

    initIMME();

    blink(300,300);

    init_RF();

    appMainInit();

    usb_up();

    /* Enable interrupts */
    EA = 1;

    BH_immeLCDInitScreen(); // Over load because we don't want the receive display function mucking up our display

    //Reset the radio to be what we want.
    //FIXME: This method is blocking
    //sleepMillis(1000);
    //setFreqState((u8) 915, 1);
    //setSyncState((u8) 3, 1);
    //setSyncByte((u8) 0x7E, 1);

    while (1)
    {  

        //poll_keyboard();
        BH_poll_keyboard(); // Over load because we will eventually use this for user input.

        appMainLoop();
        //  LED_RED = !LED_RED;
    }

}

